#include "gkt_board.h"
#include "gkt_debug.h"
#include "gkt_backboard.h"

#if defined(GKT_CONFIG_INDOOR_BELL_ENABLE) && GKT_CONFIG_INDOOR_BELL_ENABLE \
	&& (GKT_MODULE_LOC_BACKBOARD == INDOOR_BELL_LOCATION)

/* opcode */
enum {
	INDOOR_BELL_OP_PLAY = 0,
	INDOOR_BELL_OP_STOP,
	INDOOR_BELL_OP_MAX
};

enum {
	INDOOR_BELL_ST_PLAY_REQUEST = 0,
	INDOOR_BELL_ST_PLAYING,
	INDOOR_BELL_ST_STOP_REQUEST,
	INDOOR_BELL_ST_MAX
};

typedef struct {
	uint32_t	state;
	gkt_indoor_bell_notify	notify;
} indoor_bell_bb_s;
static indoor_bell_bb_s s_indoor_bell_bb;

int gkt_indoor_bell_play(void)
{
	uint8_t data[GKT_BB_APP_PACKET_MINSIZE];
	int retval;

	if ((INDOOR_BELL_ST_PLAY_REQUEST == s_indoor_bell_bb.state)
		|| (INDOOR_BELL_ST_PLAYING == s_indoor_bell_bb.state))
	{
		return GKT_EINPROCESS;
	}
	else if (INDOOR_BELL_ST_STOP_REQUEST == s_indoor_bell_bb.state)
		return GKT_EPERMIT;

	data[GKT_BB_APP_PACKET_MODULE_ID] = GKT_BB_MODULE_INDOOR_BELL;
	data[GKT_BB_APP_PACKET_OPCODE] = INDOOR_BELL_OP_PLAY;
	retval = gkt_backboard_send_data(data, GKT_BB_APP_PACKET_MINSIZE);
	if ((GKT_SUCCESS == retval) || (GKT_EINPROCESS == retval)) {
		s_indoor_bell_bb.state = INDOOR_BELL_ST_PLAY_REQUEST;
		retval = GKT_EINPROCESS;
	}

	return retval;
}

void gkt_indoor_bell_stop(void)
{
	uint8_t data[GKT_BB_APP_PACKET_MINSIZE];
	int retval;

	if ((INDOOR_BELL_ST_PLAY_REQUEST == s_indoor_bell_bb.state)
		|| (INDOOR_BELL_ST_PLAYING == s_indoor_bell_bb.state)) 
	{
		data[GKT_BB_APP_PACKET_MODULE_ID] = GKT_BB_MODULE_INDOOR_BELL;
		data[GKT_BB_APP_PACKET_OPCODE] = INDOOR_BELL_OP_STOP;
		retval = gkt_backboard_send_data(data, GKT_BB_APP_PACKET_MINSIZE);
		if ((GKT_SUCCESS == retval) || (GKT_EINPROCESS == retval))
			s_indoor_bell_bb.state = INDOOR_BELL_ST_STOP_REQUEST;
	}
}

enum {
	INDOOR_BELL_RSP_STATUS = GKT_BB_APP_PACKET_MINSIZE,
	INDOOR_BELL_RSP_MAX
};
static void indoor_bell_module_notify(int type, 
				const uint8_t *data, int length_retval)
{
	uint8_t opcode, bb_status;
	uint32_t notify_status;

	opcode = data[GKT_BB_APP_PACKET_OPCODE];
	if (opcode >= INDOOR_BELL_OP_MAX)
		return;

	notify_status = GKT_INDOOR_BELL_ST_MAX;
	if (GKT_BB_NOTIFY_PEER == type) {
		if (length_retval < INDOOR_BELL_RSP_MAX) {
			gkt_error("indoor_bell_notify: length(%u) for opcode(%u) invalid!\n",
				opcode, length_retval);
			return;
		}

		bb_status = data[INDOOR_BELL_RSP_STATUS];
		gkt_info("indoor_bell_notify: state(%u), opcode(%u), bb_status(%u)\n",
			s_indoor_bell_bb.state, opcode, bb_status);

		if (INDOOR_BELL_OP_PLAY == opcode) {
			if ((GKT_BB_STATUS_START == bb_status)
				&& (INDOOR_BELL_ST_PLAY_REQUEST == s_indoor_bell_bb.state))
			{
				s_indoor_bell_bb.state = INDOOR_BELL_ST_PLAYING;
				notify_status = GKT_INDOOR_BELL_ST_PLAY_START;
			}
			else if ((GKT_BB_STATUS_COMPLETE == bb_status)
				&& (INDOOR_BELL_ST_PLAYING == s_indoor_bell_bb.state))
			{
				s_indoor_bell_bb.state = INDOOR_BELL_ST_MAX;
				notify_status = GKT_INDOOR_BELL_ST_PLAY_END;
			}
			else if (bb_status >= GKT_BB_STATUS_ERR_BASE) {
				s_indoor_bell_bb.state = INDOOR_BELL_ST_MAX;
				notify_status = GKT_INDOOR_BELL_ST_PLAY_ERROR;
			}
		}
		else if (INDOOR_BELL_OP_STOP == opcode)
			s_indoor_bell_bb.state = INDOOR_BELL_ST_MAX;
	}
	else if (length_retval < GKT_SUCCESS)
		s_indoor_bell_bb.state = INDOOR_BELL_ST_MAX;

	if (s_indoor_bell_bb.notify
		&& (notify_status < GKT_INDOOR_BELL_ST_MAX))
	{
		(*s_indoor_bell_bb.notify)(notify_status);
	}
}

void gkt_indoor_bell_register_notify(
			gkt_indoor_bell_notify notify)
{
	s_indoor_bell_bb.notify = notify;
}

int gkt_indoor_bell_init(void)
{
	s_indoor_bell_bb.state = INDOOR_BELL_ST_MAX;
	s_indoor_bell_bb.notify = NULL;

	gkt_backboard_register_notify(GKT_BB_MODULE_INDOOR_BELL, 
		indoor_bell_module_notify);

	return GKT_SUCCESS;
}

#endif

